<?php

declare(strict_types=1);

namespace app;

use app\model\LoginLogModel;
use app\model\OperationLogModel;
use Exception;
use think\facade\Cache;
use think\facade\Db;
use think\response\Json;

/**
 * API接口基类
 * 提供通用的数据查询方法
 * Class ApiController
 * @package app
 */
class AdminController extends BaseController
{
    protected string $module = '';       // 模块名称
    protected string $controller = '';   // 控制器名称
    protected string $action = '';       // 方法名称
    protected string $requestPath = '';
    protected array $prohibitAccessArr = [
        'beforeIndex',
        'afterIndex',
        'beforeSave',
        'afterSave',
        'beforeGetInfo',
        'afterGetInfo',
        'beforeDel',
        'afterDel',
        'beforeDelAll',
        'afterDelAll',
        'executeInTransaction',
    ]; //禁止访问的方法
    protected array $params = [];        // 请求参数
    protected string|int|array $id = '0';               // 主键ID
    protected mixed $data = [];          // 结果集
    protected int $count = 0;  //总数量
    protected mixed $model = '';        // 模型
    protected mixed $validate = '';     // 验证器
    protected mixed $user = [];     // 用户数据
    protected string|array $field = '*';       // 查询字段，默认为全部
    protected array $where = [];         // 查询条件
    protected array $with = [];          // 预载入关联查询
    protected array $withJoin = [];     //join关联查询
    protected string|array $order = 'id desc';        // 排序条件
    protected string|int $page = 0;             // 分页页码
    protected string|int $pageSize = 0;         // 分页大小
    protected bool $needCount = true;   // 是否需要计数
    protected bool $isSqlMode = false;   // 是否仅生成SQL不执行
    protected bool $isDelete = false; //是否查询软删除数据


    // 初始化

    /**
     * @throws MyException|Exception
     */
    protected function initialize(): void
    {
        //获取访问模块：控制器：方法
        $hierarchical_directory = getConfigs('system_config.hierarchical_directory');
        if(!empty($hierarchical_directory)){
            $this->requestPath = ltrim(request()->baseUrl(),$hierarchical_directory);
        }else{
            $this->requestPath = request()->baseUrl();
        }

        [$this->module, $this->controller, $this->action] = explode('/',$this->requestPath);

        if (in_array($this->action, $this->prohibitAccessArr)) {
            myException('禁止访问');
        }
        $this->user   = $this->request->user;
        $this->params = $this->request->param();
        if ( ! empty($this->params['id'])) {
            $this->id = $this->params['id'];
        }
        unset($this->params['signature']);
        unset($this->params['id']);
        $this->page     = ! empty($this->params['page']) ? (int) $this->params['page'] : 0;
        $this->pageSize = ! empty($this->params['pageSize']) ? (int) $this->params['pageSize'] : 0;

        if($this->requestPath != 'admin/Login/login'){
            $auth = Cache::get(getDirectory().'permission');
            if($this->user['role_id'] != 1 && !array_key_exists($this->requestPath, $auth)){
                myException('当前账号无该操作权限');
            }
            if(!empty($auth[$this->requestPath])){
                OperationLogModel::create([
                    'system_user_id'=>$this->user['id'],
                    'role_id'=>$this->user['role_id'],
                    'dept_id'=>$this->user['dept_id'],
                    'operation'=>$auth[$this->requestPath],
                    'data'=>arrayToJson($this->params)
                ]);
            }
        }
    }

    /**
     * 通用查询方法
     * @throws Exception
     */
    protected function getList(): void
    {
        $this->data     = $this->model->getList(
            $this->where,
            $this->field,
            $this->with,
            $this->withJoin,
            $this->order,
            $this->page,
            $this->pageSize,
            $this->needCount,
            $this->isSqlMode,
            $this->isDelete,
        );
        $this->where    = [];
        $this->with     = [];
        $this->withJoin = [];
    }


    protected function getOne(): void
    {
        $this->data     = $this->model->getOne(
            $this->where,
            $this->field,
            $this->with,
            $this->withJoin,
            $this->order,
            $this->isSqlMode,
            $this->isDelete,
        );
        $this->where    = [];
        $this->with     = [];
        $this->withJoin = [];
    }


    /**
     * 新增数据
     * @return void
     */
    protected function create(): void
    {
        $res         = $this->model::create($this->params);
        $this->id    = $res->id;
        $this->data  = $res;
        $this->where = [];
    }


    /**
     * 更新数据
     * @return void
     */
    protected function update(): void
    {
        if (empty($this->where)) {
            if (is_array($this->id)) {
                $this->where = [['id', 'in', $this->id]];
            } else {
                $this->where = [['id', '=', $this->id]];
            }
        }
        $this->model::update($this->params, $this->where);
        $this->where = [];
    }


    /**
     * 删除数据
     * @throws Exception
     */
    protected function destroy(): void
    {
        if (empty($this->where)) {
            if ( ! $this->id) {
                exception('请添加删除条件');
            }
            if (is_array($this->id)) {
                $this->where = [['id', 'in', $this->id]];
            } else {
                $this->where = [['id', '=', $this->id]];
            }
        }
        $where = $this->where;
        $res   = $this->model::destroy(function ($query) use ($where) {
            $query->where($where);
        });
        if ($res === false) {
            exception('删除失败');
        }
        $this->where = [];
    }


    /**
     * 追加禁止访问的方法
     *
     * @param $value
     *
     * @return void
     */
    protected function setProhibitAccessArr($value): void
    {
        if (is_array($value)) {
            $this->prohibitAccessArr = array_merge($this->prohibitAccessArr, $value);
        } else {
            $this->prohibitAccessArr[] = $value;
        }
    }


    /**
     * 在事务中执行操作
     *
     * @param  callable  $callback
     *
     * @return Json
     */
    protected function executeInTransaction(callable $callback): Json
    {
        try {
            Db::startTrans();
            $callback();
            Db::commit();

            return success($this->id);
        } catch (\Exception $e) {
            Db::rollback();

            return error($e->getMessage());
        }
    }
}